% !Mode:: "TeX:UTF-8"
\section{几何变换}

\subsection{问题}

\begin{enumerate}
 \item 开发一个几何变换程序， 具有旋转，平移，缩放图像的功能。
 \item 要求实现最近邻插值和双线性差值方法。
\end{enumerate}


\subsection[背景原理]{背景原理}

\subsubsection{空间变换的矩阵方程}
设$g(x,y)=f(x',y')=f[a(x,y),b(x,y)]$,其中$f(x,y)$是原图像，$g(x,y)$是几何变换后图像，$a(x,y)$,$b(x,y)$可以是以下一些几何变换：
\begin{cdefi}
{\bf 平移}：
\begin{align}
&a(x,y)=x+x_0\quad b(x,y)=y+y_0 \\
&\mbox{可以被表示为矩阵方程}\notag
\\
&\begin{vmatrix}
a(x,y)\\b(x,y)\\1
\end{vmatrix}
=
\begin{vmatrix}
1&0&x_0\\
0&1&y_0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
x\\y\\1
\end{vmatrix}
\end{align}
\end{cdefi}

\begin{cdefi}
{\bf 缩放}：
\begin{align}
&a(x,y)=\frac{x}{c}\quad b(x,y)=\frac{y}{d} \\
&\mbox{可以被表示为矩阵方程}\notag
\\
&\begin{vmatrix}
a(x,y)\\b(x,y)\\1
\end{vmatrix}
=
\begin{vmatrix}
\frac{1}{c}&0&0\\
0&\frac{1}{d}&0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
x\\y\\1
\end{vmatrix}
\end{align}

\end{cdefi}

\begin{cdefi}
{\bf 旋转}：
\begin{align}
&a(x,y)=x\cos\theta-y\sin\theta \quad b(x,y)=x\sin\theta+y\cos\theta \\
&\mbox{可以被表示为矩阵方程}\notag\\
&\begin{vmatrix}
a(x,y)\\b(x,y)\\1
\end{vmatrix}
=
\begin{vmatrix}
\cos\theta&-\sin\theta&0\\
\sin\theta&\cos\theta&0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
x\\y\\1
\end{vmatrix}
\\
&\mbox{对于绕定点$(x_0,y_0)$旋转可以被表示为矩阵方程}\notag
\\
&\begin{vmatrix}
a(x,y)\\b(x,y)\\1
\end{vmatrix}
=
\begin{vmatrix}
1&0&x_0\\
0&1&y_0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
\cos\theta&-\sin\theta&0\\
\sin\theta&\cos\theta&0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
1&0&-x_0\\
0&1&-y_0\\
0&0&1
\end{vmatrix}
\begin{vmatrix}
x\\y\\1
\end{vmatrix}
\end{align}
\end{cdefi}

\subsubsection{最近邻插值}

此方法很简单，就是取距离计算出来的$f(a(x,y),b(x,y))$最近的原图像像素的灰度值

\subsubsection{双线性差值}

定义二元函数$f(x,y)=ax+by+cxy+d$其中系数$a,b,c,d$由像素$f(x,y)$的四个邻域像素 $f(0,0),f(0,1),f(1,0),f(1,1)$确定。
\begin{equation}
\left\{
\begin{array}{l}
d=f(0,0)\\
a+d=f(1,0)\\
b+d=f(0,1)\\
a+b+c+d=f(1,1)
\end{array}
\right.
\end{equation}
变换图像的灰度值由以上函数计算得出。

\subsection{程序代码说明}

本实验程序文件为 src/q2\_geometric\_transform/q2.py,主要通过numpy提供的矩阵运算功能来实现。其中：

{\bf find\_nei}函数用以发现邻居。

{\bf transform}函数用以根据变换矩阵和插值方法进行几何变换。

{\bf nearest}函数用以实现最近邻插值方法。

{\bf bilinear}函数用以实现双线性插值方法。

\subsection{实验结果与分析}
\subsubsection{几何变换结果}
分别使用最近邻插值和双线性插值法进行平移、缩放、旋转的结果如下：
\begin{longtable}{ll}
\caption{几何变换} \\
%\toprule
%\multicolumn{2}{c}{几何变换} \\
%\midrule
%\endfirsthead
%\midrule
%\multicolumn{2}{c}{几何变换} \\
%\midrule
\endhead
\midrule
\multicolumn{2}{r}{接下页\dots} \\
\endfoot
\endlastfoot
\hline
平移$x_0=50,y_0=20$\,最近邻插值 &平移$x_0=50,y_0=20$\,双线性插值 \\
\includegraphics[height=5cm]{../output/Q2_translation_nearest.jpg} &\includegraphics[height=5cm]{../output/Q2_translation_bilinear.jpg} \\
\hline
缩放$c=d=0.5$\,最近邻插值 &缩放$c=d=0.5$\,双线性插值\\

\includegraphics[height=5cm]{../output/Q2_scale_nearest.jpg} &\includegraphics[height=5cm]{../output/Q2_scale_bilinear.jpg} \\
\hline
旋转$\theta=\frac{\pi}{2}$\,最近邻插值 &旋转$\theta=\frac{\pi}{2}$\,双线性插值\\

\includegraphics[height=5cm]{../output/Q2_rotation_nearest.jpg} &\includegraphics[height=5cm]{../output/Q2_rotation_bilinear.jpg} \\
\bottomrule
\end{longtable}

\subsubsection{分析}
使用变换矩阵来表示几何变换，统一了不同变换的形式，并极大地简化了程序的编写。同时两种插值算法，有细微的视觉差别。双线性插值对细节的清晰度表现略优于最近邻插值法。但是最近邻插值算法的运算速度较快。



